/*
PearReview - The peer review assistant.
Copyright (C) 2009  Dimitrij Pankratz, Anton Musichin
http://www.pearreview.com, info@pearreview.com

This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
*/

package com.pearreview.util.review.io;

import java.io.File;
import java.io.OutputStream;

import javax.xml.datatype.DatatypeConfigurationException;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.transform.Result;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerException;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;

import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.Text;

import com.pearreview.util.review.Aspect;
import com.pearreview.util.review.Catalog;

public class XMLCatalogWriter implements CatalogWriter {

	private static final long serialVersionUID = 4051234399234177398L;
	
	public final static String NAMESPACE = 
			"http://www.informatik.uni-stuttgart.de/iste/se";
	private String prefix = "resi";
	
	public XMLCatalogWriter() {
		super();
	}
	
	public XMLCatalogWriter(String prefix) throws 
			DatatypeConfigurationException {
		this();
		setPrefix(prefix);
	}
	
	public void setPrefix(String prefix) {
		this.prefix = prefix;
	}

	@Override
	public void write(Catalog catalog, File file) throws NullPointerException, 
			TransformerException, ParserConfigurationException {
		write(catalog, new StreamResult(file));
	}
	
	@Override
	public void write(Catalog catalog, OutputStream outpuStream) 
			throws NullPointerException, TransformerException, 
			ParserConfigurationException {
		write(catalog, new StreamResult(outpuStream));
	}
	
	public void write(Catalog catalog, Result result) 
			throws NullPointerException, TransformerException, 
			ParserConfigurationException {
		Transformer tr = TransformerFactory.newInstance().newTransformer();
		tr.transform(new DOMSource(create(catalog)), result);
	}
	
	protected Document create(Catalog catalog)
		throws ParserConfigurationException, NullPointerException {
		DocumentBuilder docBuilder = 
				DocumentBuilderFactory.newInstance().newDocumentBuilder();
			
		//create document instance
		Document doc = docBuilder.newDocument();
		
		/* catalog */
		doc.appendChild(createCatalog(catalog, doc));
		
		return doc;
	}
	
	protected Element createCatalog(Catalog catalog, Document doc) {
		Element catalogRoot = doc.createElementNS(NAMESPACE, "catalog");
		catalogRoot.setPrefix(prefix);
		
		/* catalog description */
		if(catalog.getDescription() != null) {
			Element name = doc.createElementNS(NAMESPACE, "description");
			name.setPrefix(prefix);
			Node value = doc.createCDATASection(catalog.getDescription());
			name.appendChild(value);
			catalogRoot.appendChild(name);
		}
		
		/* catalog aspects */
		if(catalog.getAspects() != null) {
			Element aspects = doc.createElementNS(NAMESPACE, "aspects");
			aspects.setPrefix(prefix);
			for (Aspect currentAspect: catalog.getAspects()) {
				if(currentAspect == null)
					continue;
				Element aspect = createAspect(currentAspect, doc);
				aspects.appendChild(aspect);
			}
			catalogRoot.appendChild(aspects);
		}
		
		return catalogRoot;
	}
	
	protected Element createAspect(Aspect aspect, Document doc) {
		Element aspectRoot = doc.createElementNS(NAMESPACE, "aspect");
		aspectRoot.setPrefix(prefix);
		
		/* aspect id */
		if(aspect.getId() != null) {
			Element id = doc.createElementNS(NAMESPACE, "id");
			id.setPrefix(prefix);
			Text value = doc.createTextNode(aspect.getId());
			id.appendChild(value);
			id.appendChild(value);
			aspectRoot.appendChild(id);
		}
		
		/* aspect category */
		if(aspect.getCategory() != null) {
			Element category = doc.createElementNS(NAMESPACE, "category");
			category.setPrefix(prefix);
			Node value = doc.createCDATASection(aspect.getCategory());
			category.appendChild(value);
			aspectRoot.appendChild(category);
		}
		
		/* aspect directive */
		if(aspect.getDirective() != null) {
			Element directive = doc.createElementNS(NAMESPACE, "directive");
			directive.setPrefix(prefix);
			Node value = doc.createCDATASection(aspect.getDirective());
			directive.appendChild(value);
			aspectRoot.appendChild(directive);
		}
		
		/* aspect description */
		if(aspect.getDescription() != null) {
			Element description = doc.createElementNS(NAMESPACE, "description");
			description.setPrefix(prefix);
			Node value = doc.createCDATASection(aspect.getDescription());
			description.appendChild(value);
			aspectRoot.appendChild(description);
		}
		
		return aspectRoot;
	}
}
